package org.jeecg.modules.analysis.graph.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.analysis.graph.entity.Graph;
import org.jeecg.modules.analysis.graph.service.IGraphService;
import org.jeecg.modules.demo.patent.entity.Patent;
import org.jeecg.modules.demo.patent.mapper.PatentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 专利图谱Service实现
 * @Author: jeecg-boot
 * @Date: 2025-01-10
 */
@Service
@Slf4j
public class GraphServiceImpl implements IGraphService {

    @Autowired
    private PatentMapper patentMapper;

    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");


    @Override
    public List<Graph> getGraphList(String patentId, String type, Integer maxNodes) {


        // 1. 查询核心专利
        Patent corePatent = patentMapper.selectById(patentId);
        if (corePatent == null) {
            log.warn("未找到核心专利: {}", patentId);
            return null;
        }

        List<Graph> graphList = new ArrayList<>();

        // 2. 添加核心专利节点
        Graph coreNode = convertPatentToGraph(corePatent, true, 1.0);
        graphList.add(coreNode);

        // 3. 根据关联类型查询关联专利
        List<Patent> relatedPatentList = queryRelatedPatents(corePatent, type, maxNodes);

        // 4. 转换关联专利为图谱节点
        for (Patent relatedPatent : relatedPatentList) {
            double relationValue = calculateRelationValue(corePatent, relatedPatent, type);
            Graph graphNode = convertPatentToGraph(relatedPatent, false, relationValue);
            graphList.add(graphNode);
        }

        log.info("成功查询到图谱数据: 核心专利1个, 关联专利{}个", relatedPatentList.size());
        return graphList;


    }

    /**
     * 查询关联专利
     */
    private List<Patent> queryRelatedPatents(Patent corePatent, String type, Integer maxNodes) {
        QueryWrapper<Patent> queryWrapper = new QueryWrapper<>();

        // 排除核心专利自己
        queryWrapper.ne("id", corePatent.getId());

        switch (type) {
            case "institution":
                // 申请机构关联
                if (StringUtils.hasText(corePatent.getApplyInstitutionOriginName())) {
                    queryWrapper.eq("apply_institution_origin_name", corePatent.getApplyInstitutionOriginName());
                } else if (StringUtils.hasText(corePatent.getApplyInstitutionZhName())) {
                    queryWrapper.eq("apply_institution_zh_name", corePatent.getApplyInstitutionZhName());
                }
                break;

            case "inventor":
                // 发明人关联 - 模糊匹配
                if (StringUtils.hasText(corePatent.getInventorOriginName())) {
                    String[] inventors = corePatent.getInventorOriginName().split("[,;，；]");
                    if (inventors.length > 0) {
                        for (String inventor : inventors) {
                            inventor = inventor.trim();
                            if (inventor.length() > 0) {
                                queryWrapper.or().like("inventor_origin_name", inventor);
                            }
                        }
                    }
                }
                break;

            case "ipc":
                // IPC分类关联
                if (StringUtils.hasText(corePatent.getIpcClassId())) {
                    // 提取IPC大类（前4个字符）
                    String ipcPrefix = corePatent.getIpcClassId().length() >= 4
                        ? corePatent.getIpcClassId().substring(0, 4)
                        : corePatent.getIpcClassId();
                    queryWrapper.like("ipc_class_id", ipcPrefix);
                }
                break;

            case "technology":
                // 技术领域关联 - 这里简单用IPC分类代替
                // 实际项目中可能需要一个单独的技术领域字段
                if (StringUtils.hasText(corePatent.getIpcClassId())) {
                    String ipcPrefix = corePatent.getIpcClassId().length() >= 3
                        ? corePatent.getIpcClassId().substring(0, 3)
                        : corePatent.getIpcClassId();
                    queryWrapper.like("ipc_class_id", ipcPrefix);
                }
                break;

            default:
                log.warn("未知的关联类型: {}", type);
                return new ArrayList<>();
        }

        // 限制返回数量
        queryWrapper.last("LIMIT " + (maxNodes != null ? maxNodes : 20));

        return patentMapper.selectList(queryWrapper);
    }

    /**
     * 计算关联度
     */
    private double calculateRelationValue(Patent corePatent, Patent relatedPatent, String type) {
        try {
            switch (type) {
                case "institution":
                    // 申请机构完全相同：0.9-1.0
                    if (isSameInstitution(corePatent, relatedPatent)) {
                        return 0.9 + Math.random() * 0.1;
                    }
                    return 0.7 + Math.random() * 0.2;

                case "inventor":
                    // 计算共同发明人比例
                    return calculateInventorSimilarity(corePatent, relatedPatent);

                case "ipc":
                    // IPC分类相似度
                    return calculateIpcSimilarity(corePatent, relatedPatent);

                case "technology":
                    // 技术领域相似度
                    return 0.6 + Math.random() * 0.3;

                default:
                    return 0.5;
            }
        } catch (Exception e) {
            log.error("计算关联度失败", e);
            return 0.5;
        }
    }

    /**
     * 判断是否为相同机构
     */
    private boolean isSameInstitution(Patent p1, Patent p2) {
        if (StringUtils.hasText(p1.getApplyInstitutionOriginName())
            && StringUtils.hasText(p2.getApplyInstitutionOriginName())) {
            return p1.getApplyInstitutionOriginName().equals(p2.getApplyInstitutionOriginName());
        }
        if (StringUtils.hasText(p1.getApplyInstitutionZhName())
            && StringUtils.hasText(p2.getApplyInstitutionZhName())) {
            return p1.getApplyInstitutionZhName().equals(p2.getApplyInstitutionZhName());
        }
        return false;
    }

    /**
     * 计算发明人相似度
     */
    private double calculateInventorSimilarity(Patent p1, Patent p2) {
        Set<String> inventors1 = parseInventors(p1.getInventorOriginName());
        Set<String> inventors2 = parseInventors(p2.getInventorOriginName());

        if (inventors1.isEmpty() || inventors2.isEmpty()) {
            return 0.5;
        }

        // 计算交集
        Set<String> intersection = new HashSet<>(inventors1);
        intersection.retainAll(inventors2);

        // 计算相似度
        int maxSize = Math.max(inventors1.size(), inventors2.size());
        return (double) intersection.size() / maxSize;
    }

    /**
     * 计算IPC相似度
     */
    private double calculateIpcSimilarity(Patent p1, Patent p2) {
        String ipc1 = p1.getIpcClassId();
        String ipc2 = p2.getIpcClassId();

        if (!StringUtils.hasText(ipc1) || !StringUtils.hasText(ipc2)) {
            return 0.5;
        }

        // 完全相同
        if (ipc1.equals(ipc2)) {
            return 1.0;
        }

        // 大类相同（前4个字符）
        if (ipc1.length() >= 4 && ipc2.length() >= 4
            && ipc1.substring(0, 4).equals(ipc2.substring(0, 4))) {
            return 0.7 + Math.random() * 0.2;
        }

        // 部类相同（前3个字符）
        if (ipc1.length() >= 3 && ipc2.length() >= 3
            && ipc1.substring(0, 3).equals(ipc2.substring(0, 3))) {
            return 0.5 + Math.random() * 0.2;
        }

        return 0.3 + Math.random() * 0.2;
    }

    /**
     * 解析发明人字符串为集合
     */
    private Set<String> parseInventors(String inventors) {
        Set<String> inventorSet = new HashSet<>();
        if (!StringUtils.hasText(inventors)) {
            return inventorSet;
        }

        String[] parts = inventors.split("[,;，；]");
        for (String part : parts) {
            String inventor = part.trim();
            if (inventor.length() > 0) {
                inventorSet.add(inventor);
            }
        }
        return inventorSet;
    }

    /**
     * 将Patent实体转换为Graph节点
     */
    private Graph convertPatentToGraph(Patent patent, boolean isCore, double relationValue) {
        Graph graph = new Graph();

        // 基本信息（与Patent实体字段保持一致）
        graph.setId(patent.getId());
        graph.setZhName(patent.getZhName());
        graph.setOriginName(patent.getOriginName());
        graph.setApplyId(patent.getApplyId());

        // 机构信息（与Patent实体字段保持一致）
        String applyInstitutionZhName = StringUtils.hasText(patent.getApplyInstitutionZhName())
            ? patent.getApplyInstitutionZhName()
            : patent.getApplyInstitutionOriginName();
        graph.setApplyInstitutionZhName(applyInstitutionZhName);

        // 发明人信息（与Patent实体字段保持一致）
        String inventorZhName = StringUtils.hasText(patent.getInventorZhName())
            ? patent.getInventorZhName()
            : patent.getInventorOriginName();
        graph.setInventorZhName(inventorZhName);

        // 转换为发明人列表（DTO扩展字段）
        if (StringUtils.hasText(inventorZhName)) {
            List<String> inventorList = Arrays.stream(inventorZhName.split("[,;，；]"))
                .map(String::trim)
                .filter(s -> s.length() > 0)
                .collect(Collectors.toList());
            graph.setInventorList(inventorList);
        }

        // 日期信息（与Patent实体字段保持一致）
        if (patent.getApplyDate() != null) {
            graph.setApplyDate(DATE_FORMAT.format(patent.getApplyDate()));
        }
        if (patent.getApplyPublicDate() != null) {
            graph.setApplyPublicDate(DATE_FORMAT.format(patent.getApplyPublicDate()));
        }

        // IPC分类（与Patent实体字段保持一致）
        graph.setIpcClassId(patent.getIpcClassId());

        // 技术领域（DTO扩展字段，从IPC分类派生）
        if (StringUtils.hasText(patent.getIpcClassId())) {
            graph.setTechnology(extractTechnologyFromIpc(patent.getIpcClassId()));
        }

        // 法律状态（DTO扩展字段）
        graph.setLegalStatus("有效"); // 简化处理，实际应从数据库字段获取

        // 摘要（与Patent实体字段保持一致）
        graph.setSummary(patent.getSummary());
        graph.setSummaryZh(patent.getSummaryZh());

        // 文件（与Patent实体字段保持一致）
        graph.setFileString(patent.getFileString());

        // 图谱相关属性（DTO扩展字段）
        graph.setIsCore(isCore);
        graph.setRelationValue(relationValue);

        return graph;
    }

    /**
     * 从IPC分类提取技术领域
     */
    private String extractTechnologyFromIpc(String ipc) {
        if (!StringUtils.hasText(ipc) || ipc.length() < 1) {
            return "未知";
        }

        // IPC第一个字母代表部
        char section = ipc.charAt(0);
        switch (section) {
            case 'A': return "人类生活必需";
            case 'B': return "作业；运输";
            case 'C': return "化学；冶金";
            case 'D': return "纺织；造纸";
            case 'E': return "固定建筑物";
            case 'F': return "机械工程";
            case 'G': return "物理";
            case 'H': return "电学";
            default: return "其他";
        }
    }
}

